using System.IO;
using System.Net.Security;
using System.Net.Sockets;

namespace MonoNZB.NNTP
{
	public class Client : TcpClient
	{
		public bool PostingAllowed { get; set; }
		
		private Server _server;
		private Stream _stream;
		
		public void Connect(Server Server) {
			_server = Server;
			
			base.Connect(_server.Hostname, _server.Port);
			
			Stream stream = GetStream();
			StreamReader reader = new StreamReader(stream);
			string response = reader.ReadLine();
			
			if (response.StartsWith("200"))
			{
				PostingAllowed = true;	
			}
			else if (response.StartsWith("201"))
			{
				PostingAllowed = false;	
			}
			else if (!response.StartsWith("2"))
			{
				Close();	
			}
			
			return;
		}
		
		public void Authenticate()
		{
			Stream stream = GetStream();
			StreamWriter writer = new StreamWriter(stream);
			StreamReader reader = new StreamReader(stream);
			
			if (writer == null || reader == null)
			{
				Close();	
			}
			
			writer.AutoFlush = true;
			writer.WriteLine("AUTHINFO USER " + _server.Username);
			writer.WriteLine("AUTHINFO PASS " + _server.Password);
			string response = reader.ReadLine();
			
			if (response.StartsWith("482") || response.StartsWith("502"))
			{
				Close();
			}
			
			if (!response.StartsWith("281"))
			{
				writer.WriteLine("AUTHINFO GENERIC " + _server.Username + " " + _server.Password);
				response = reader.ReadLine();
				
				if (response.StartsWith("502"))
				{
					Close();	
				}
				else if (!response.StartsWith("281"))
				{
					writer.WriteLine("AUTHINFO SIMPLE");
					writer.WriteLine(_server.Username + " " + _server.Password);
					response = reader.ReadLine();
					
					if (!response.StartsWith("250"))
					{
						Close();	
					}
					else
					{
						return;	
					}
				}
				else
				{
					return;	
				}
			}
			else
			{
				return;	
			}
		}
		
		public new void Close()
		{
			Stream stream = GetStream();
			StreamWriter writer = new StreamWriter(stream);
			writer.AutoFlush = true;
			
			try
			{
				writer.WriteLine("QUIT");	
			}
			catch
			{
			}
			
			base.Close();
		}
		
		public new Stream GetStream()
		{
			if (!Connected || _stream == null)
			{
				_stream = base.GetStream();
				
				if (_server.SSL)
				{
					SslStream sslStream = new SslStream(_stream, true);
					sslStream.AuthenticateAsClient(_server.Hostname);
					_stream = sslStream;
				}
			}
			
			return _stream;
		}
	}
}
